package ${tempValues.package_this_file};

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class RedisConfig {

<#if redis?? && redis.host??>
    @Value("${redis.host}")
    private String host;
<#else>
    @Value("${r'${spring.redis.host}'}")
    private String host;
</#if>

<#if redis?? && redis.port??>
    @Value("${redis.port}")
    private Integer port;
<#else>
    @Value("${r'${spring.redis.port}'}")
    private Integer port;
</#if>

<#if redis?? && redis.username??>
    @Value("${redis.username}")
    private String username;
<#else>
    @Value("${r'${spring.redis.username:}'}")
    private String username;
</#if>

<#if redis?? && redis.password??>
    @Value("${redis.password}")
    private String password;
<#else>
    @Value("${r'${spring.redis.password:}'}")
    private String password;
</#if>

    @Value("${r'${spring.redis.database:0}'}")
    private Integer database;
    @Value("${r'${spring.redis.timeout:5000}'}")
    private Integer timeout;
    @Value("${r'${spring.redis.lettuce.pool.max-active:3}'}")
    private Integer poolMaxActive;
    @Value("${r'${spring.redis.lettuce.pool.min-idle:2}'}")
    private Integer poolMinIdle;
    @Value("${r'${spring.redis.lettuce.pool.max-idle:3}'}")
    private Integer poolMaxIdle;
    @Value("${r'${spring.redis.lettuce.pool.max-wait:-1}'}")
    private Integer poolMaxWait;
    @Value("${r'${spring.redis.lettuce.shutdown-timeout:100}'}")
    private Integer shutdownTimeout;
    @Value("${r'${spring.cache.redis.cache-null-values:true}'}")
    private String nullValues;

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxIdle(poolMaxIdle);
        genericObjectPoolConfig.setMinIdle(poolMinIdle);
        genericObjectPoolConfig.setMaxTotal(poolMaxActive);
        genericObjectPoolConfig.setMaxWaitMillis(poolMaxWait);
        genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(100);
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setDatabase(database);
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setUsername(username);
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
            .commandTimeout(Duration.ofMillis(timeout))
            .shutdownTimeout(Duration.ofMillis(shutdownTimeout))
            .poolConfig(genericObjectPoolConfig)
            .build();

        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
        return factory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }
}